package com.example.librarymanagementsystembackend.utils;

import io.swagger.v3.core.converter.ModelConverters;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.media.*;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.customizers.OperationCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.ResolvableType;
import org.springframework.http.ResponseEntity;

import java.util.List;

@Configuration
public class Knife4jConfig {
    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                .openapi("3.0.0")
                .info(new Info()
                        .title("API文档")
                        .version("1.0")
                        .description("图书管理系统API文档"));
//                .externalDocs(new ExternalDocumentation()
//                        .description("参考文档")
//                        .url("https://doc.xiaominfo.com")
//                );
    }

    @Bean("operationCustomizer")
    public OperationCustomizer operationCustomizer() {
        return (operation, handlerMethod) -> {
            // 获取原始返回类型
            Class<?> returnType = handlerMethod.getMethod().getReturnType();
            // 排除已经封装的响应类型、响应实体类型
            if (returnType.isAssignableFrom(ResponseData.class)
                    || returnType.isAssignableFrom(ResponseEntity.class)) {
                return operation;
            }

            // 其他类型自动包装到data字段
            try {
                operation.getResponses().get("200").getContent()
                        .forEach((mediaType, content) -> {
                            // 获取统一响应体模型模板
                            Schema<?> responseDataTemplateSchema = ModelConverters.getInstance()
                                    .read(ResponseData.class)
                                    .get("ResponseData");
                            // 深度克隆Schema（包括所有属性）
                            Schema<?> responseDataSchema = new Schema()
                                    .type(responseDataTemplateSchema.getType())
                                    .description(responseDataTemplateSchema.getDescription())
                                    .required(responseDataTemplateSchema.getRequired())
                                    .properties(responseDataTemplateSchema.getProperties());
                            // 获取原始响应体模型
                            Schema<?> originalSchema;
                            ResolvableType resolvableType = ResolvableType.forMethodReturnType(handlerMethod.getMethod());
                            if (resolvableType.getRawClass() == List.class) {
                                ResolvableType elementType = resolvableType.getGeneric(0); // 获取 List<T> 中的 T
                                Schema<?> elementSchema = ModelConverters.getInstance().read(elementType.getRawClass()).get(elementType.resolve().getSimpleName());
                                originalSchema = new ArraySchema().items(elementSchema);
                            }
                            else if (returnType == String.class) {
                                originalSchema = new StringSchema();
                            }
                            else {
                                originalSchema = ModelConverters.getInstance()
                                        .read(returnType)
                                        .get(returnType.getSimpleName());
                            }
                            responseDataSchema.addProperty("data", originalSchema);
                            content.setSchema(responseDataSchema);
                        });
            } catch(NullPointerException e) {
                System.out.println(e.getMessage());
            }

            return operation;
        };
    }

    @Bean
    public GroupedOpenApi bookManagementApi() {
        return GroupedOpenApi.builder()
                .group("图书管理")
                .pathsToMatch("/book/**")
                .packagesToScan("com.example.librarymanagementsystembackend.bookmanagement")
                .addOperationCustomizer(this.operationCustomizer())
                .build();
    }

    @Bean
    public GroupedOpenApi borrowingManagementApi() {
        return GroupedOpenApi.builder()
                .group("借阅管理")
                .pathsToMatch("/borrowing/**")
                .packagesToScan("com.example.librarymanagementsystembackend.borrowingmanagement")
                .addOperationCustomizer(this.operationCustomizer())
                .build();
    }

    @Bean
    public GroupedOpenApi userManagementApi() {
        return GroupedOpenApi.builder()
                .group("用户管理")
                .pathsToMatch("/user/**", "/userActions/**", "/login")
                .packagesToScan("com.example.librarymanagementsystembackend.usermanagement")
                .addOperationCustomizer(this.operationCustomizer())
                .build();
    }

    @Bean
    public GroupedOpenApi systemManagementApi() {
        return GroupedOpenApi.builder()
                .group("系统管理")
                .pathsToMatch("/system/**")
                .packagesToScan("com.example.librarymanagementsystembackend.systemicfunctions")
                .addOperationCustomizer(this.operationCustomizer())
                .build();
    }
}
